package com.bocek.chakmapoint.model;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class SlideList {

	private static ArrayList<Slide> slides = new ArrayList<Slide>();

	public SlideList() {
	}
	
	public static ArrayList<Slide> getSlides() {
		return slides;
	}

	public static void appendSlide(Slide slide) {
		slides.add(slide);
	}

	public static void insertSlideInto(Slide slide, int location) {
		slides.add(location - 1, slide);
	}

	public static Slide getSlide(int slideNo) {
		return slides.get(slideNo - 1);
	}

	public static void moveLeft(Slide slide) {
		int position = slides.indexOf(slide);

		slides.remove(slide);

		slides.add(position - 1, slide);
	}

	public static void moveRight(Slide slide) {
		int position = slides.indexOf(slide);

		slides.remove(slide);

		slides.add(position + 1, slide);
	}
	

	public static void deleteSlide(Slide slide) {
		slides.remove(slide);
	}

	public static void setSlides(ArrayList<Slide> s){
		slides.clear();
		slides.addAll(s);
	}

	public static void saveToXML(String filename) throws ParserConfigurationException{
		/*
			 <presentation name="" styleName="" numSlides="1">
				<slides>
					<slide title="" numObjects="1" slideNum="1">
						<objects>
							<zigzaglines>
								<zigzagline thickness="" color="" depth="1">

		 */
		
		// DEFAULT
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		DocumentBuilder db = dbf.newDocumentBuilder();
		Document doc = db.newDocument();
		
		Element p = doc.createElement("presentation");
		p.setAttribute("name", "");
		p.setAttribute("styleName", SlideStyleList.getInstance().getStyle(SlideStyleList.getInstance().getCurrent()).getName());
		p.setAttribute("numSlides", Integer.toString(slides.size()));
		
		Element sl = doc.createElement("slides");
		for(int i=0;i<slides.size();i++){
			Element s = doc.createElement("slide");
			s.setAttribute("title", slides.get(i).getName());
			s.setAttribute("numObjects", Integer.toString(slides.get(i).getSlideItems().size()));
			s.setAttribute("slideNum", Integer.toString(i+1));
			
			Element z = doc.createElement("zigzaglines");
			Element r = doc.createElement("rectangles");
			Element e = doc.createElement("elipses");
			Element t = doc.createElement("textboxes");
			
			
			Element o = doc.createElement("objects");
			
			for(int j=0; j<slides.get(i).getSlideItems().size();j++){
				SlideItem temp = slides.get(i).getSlideItems().get(j);
				if(temp.getName().equalsIgnoreCase("zigzagline")){
					z.appendChild(temp.saveToXML(doc, j+1));
				}
				
				if(temp.getName().equalsIgnoreCase("rectangle")){
					r.appendChild(temp.saveToXML(doc, j+1));
				}
				
				if(temp.getName().equalsIgnoreCase("oval")){
					o.appendChild(temp.saveToXML(doc, j+1));
				}
				
				if(temp.getName().equalsIgnoreCase("text")){
					t.appendChild(temp.saveToXML(doc, j+1));
				}
				
				o.appendChild(z);
				o.appendChild(r);
				o.appendChild(e);
				o.appendChild(t);
			}
			
			s.appendChild(o);
			sl.appendChild(s);	
		}
		
		p.appendChild(sl);
		
		// create document
		doc.appendChild(p);

		// Now, we will simply transform DOM into a file (source into result)
		Transformer transform;
		
		// Generate output file (result)
		File file = new File(filename);
		Result result = new StreamResult(file);
		
		try {
			Source source = new DOMSource(doc);
			
			// Validation
//			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
//		    Schema xsd = schemaFactory.newSchema(new File("presentation.xsd"));
//		    Validator validator = xsd.newValidator();
//		    validator.validate(source);

			
			// initialize the transformer
			transform = TransformerFactory.newInstance().newTransformer();
			
			// property
			transform.setOutputProperty(OutputKeys.INDENT, "yes"); // indent lines
			transform.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); // first line 
			transform.setOutputProperty(OutputKeys.METHOD, "xml"); // not required, it's to be specific
			
			// transform source into result
			transform.transform(source, result);	
		}
		catch (TransformerConfigurationException err) {
			err.printStackTrace();
		}
		catch (TransformerFactoryConfigurationError err) {
			err.printStackTrace();
		}
		catch (TransformerException err) {
			err.printStackTrace();
		}
//		catch (SAXException err) {
//			err.printStackTrace();
//		}
//		catch (IOException err) {
//			err.printStackTrace();
//		}
		
	}
	
	public static ArrayList<Slide> loadFromXML(String filename){
		// DEFAULT
		File file = new File(filename);
		Document doc = null;
		DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

		try{
			DocumentBuilder db = dbf.newDocumentBuilder();
			doc = db.parse(file);
			
			// Validation
			SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
		    Schema xsd = schemaFactory.newSchema(new File("presentation.xsd"));
		    Validator validator = xsd.newValidator();
		    Source source = new DOMSource(doc);
		    validator.validate(source);
		    
		    
		}
		catch(ParserConfigurationException e) {
			e.printStackTrace();
		}
		catch(SAXException e){
			e.printStackTrace();
		}
		catch(IOException e) {
			e.printStackTrace();
		}
		
		return null;
	}
}
